package com.haixee.parkdemo.gateway.filter;

import com.haixee.parkdemo.common.exception.BusinessException;
import com.haixee.parkdemo.common.response.CommonResEnum;
import com.haixee.parkdemo.common.response.ResResult;
import com.haixee.parkdemo.common.response.ResUtil;
import com.haixee.parkdemo.gateway.utils.RequestUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

/**
 * 审计过略器
 * @author GUIFENG GUO
 * 2020/9/10 16:20
 */
@Slf4j
//@Component
public class AuditFilter implements GlobalFilter, Ordered {

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {

        ServerHttpRequest request = exchange.getRequest();
        String ip = RequestUtil.getIp(request);
        // User-Agent
        String userAgent = RequestUtil.getValueFromHeader(request.getHeaders(), "User-Agent");
        String method = request.getMethodValue();
        String uri = request.getURI().getPath();
        long time = System.currentTimeMillis();

        // 全局上下文
        exchange.getAttributes().put("ip", ip);
        exchange.getAttributes().put("uri", uri);


        return chain.filter(exchange).doOnSuccess(ctx -> {

            Integer uid = (Integer) exchange.getAttributes().get("uid");

            long latency = System.currentTimeMillis() - time;
            log.info("HTTP LOG: uid={}, ip={}, latency={}, method={}, url={}, user-agent={}",
                    uid, ip, latency, method, uri, userAgent);
        }).onErrorResume(e -> {

            // 下游过滤器执行失败,输出信息
            HttpStatus httpStatus = HttpStatus.OK;
            CommonResEnum resEnum = CommonResEnum.UNKNOWN_ERROR;

            Integer code = resEnum.getCode();
            String msg = resEnum.getMsg();
            String consoleMsg = e.getMessage();

            if (e instanceof BusinessException) {
                BusinessException businessException = (BusinessException) e;
                code = businessException.getCode();
                msg = businessException.getMessage();

//                if (code > 2000 && code < 3000) {
//                    msg = CommonResEnum.PERMISSION_DENIED.getMsg();
//                }
            } else {
                e.printStackTrace();
            }

            long latency = System.currentTimeMillis() - time;
            log.error("HTTP LOG: ip={}, latency={}, method={}, url={}, user-agent={}, msg={}", ip, latency, method, uri, userAgent, consoleMsg);

            ResResult commonRes = ResUtil.error(code, msg);
            return RequestUtil.writeResponse(exchange.getResponse(), httpStatus, commonRes);
        });
    }

    @Override
    public int getOrder() {
        return -10;
    }
}
